package com.devshephard.jucks.pc;


import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class syncPcLock {

    public static void main(String[] args) {


        DataLock data = new DataLock();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.crement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.crement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();

        new Thread(()->{
            for (int i = 0; i < 20; i++) {
                try {
                    data.decrement();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"D").start();
    }


}


class DataLock{

    public  Integer number = 0;

    private Lock lock = new ReentrantLock();

    private Condition condition = lock.newCondition();


    public  void crement() throws InterruptedException {

        lock.lock();

        try{
            /**
             * 这里切记要使用while，否则会出现虚假唤醒的问题
             * 结论：就是用if判断的话，唤醒后线程会从wait之后的代码开始运行，但是不会重新判断if条件，
             * 直接继续运行if代码块之后的代码，而如果使用while的话，也会从wait之后的代码运行，但是唤醒后会重新判断循环条件，如果不成立再执行while代码块之后的代码块，成立的话继续wait。
             * 这也就是为什么用while而不用if的原因了，因为线程被唤醒后，执行开始的地方是wait之后。
             */
            while (number != 0){
                condition.await();
            }
            number ++;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

    public  void decrement() throws InterruptedException {

        lock.lock();

        try{
            while(number == 0){
                condition.await();
            }
            number --;
            System.out.println(Thread.currentThread().getName() + "=>" + number);
            condition.signalAll();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            lock.unlock();
        }
    }

}
